#ifndef _SD_DRV_H_
#define _SD_DRV_H_ 

#define HW_SD_BASE                    	0x00001000
	
/* define SD card register */
#define HW_SD_STATUS       				(HW_SD_BASE+0x000)
#define HW_SD_CMD_CON      				(HW_SD_BASE+0x004)
#define HW_SD_CMD_ARG      				(HW_SD_BASE+0x008)
#define HW_SD_RSP_IND      				(HW_SD_BASE+0x00C)
#define HW_SD_RSP_ARG1     				(HW_SD_BASE+0x010)
#define HW_SD_RSP_ARG2     				(HW_SD_BASE+0x014)
#define HW_SD_RSP_ARG3     				(HW_SD_BASE+0x018)
#define HW_SD_RSP_ARG4     				(HW_SD_BASE+0x01c)
#define HW_SD_TIMEOUT     				(HW_SD_BASE+0x020)
#define HW_SD_DATA_CON     				(HW_SD_BASE+0x024)
#define HW_SD_DATA_LEN     				(HW_SD_BASE+0x028)
#define HW_SD_MASK	     				(HW_SD_BASE+0x02C)
#define HW_SD_CLK_CON     				(HW_SD_BASE+0x030)
#define HW_SD_PWR_CON     				(HW_SD_BASE+0x034)
#define HW_SD_BLOCK_CON     			(HW_SD_BASE+0x038)
#define HW_SD_SRAM_RDCLK_CON    		(HW_SD_BASE+0x03C)
#define HW_SD_CLK_DFG					(HW_SD_BASE+0x058)
#define HW_SD_FIFO_POINT				(HW_SD_BASE+0x05C)
#define HW_SD_FIFO_COUNTER				(HW_SD_BASE+0x060)
#define SD_FIFO_ADDR					(HW_SD_BASE+0x080)


/* HW_SD_CMD_CON */
/* define SD card command */
#define SD_CMD0			0x00000101
#define SD_CMD1			0x00050101
#define SD_CMD2			0x000a0101
#define SD_CMD3			0x000d0101
#define SD_CMD7			0x001d0101
#define SD_CMD9			0x00260101
#define SD_CMD12		0x00310101
#define SD_CMD13		0x00350101
#define SD_CMD15		0x003c0101
#define SD_CMD17		0x00450101
#define SD_CMD18		0x00490101
#define SD_CMD24		0x00610101
#define SD_CMD25		0x00650101
#define SD_CMD32		0x00810101
#define SD_CMD33		0x00850101
#define SD_CMD38		0x00990101
#define SD_CMD55		0x00dd0101

#define SD_ACMD6		0x00190101
#define SD_ACMD41		0x00a50101
#define SD_ACMD42		0x00a90101

/* HW_SD_STATUS  the value set to SD card status register */
#define SD_CMD_DONE_CMD_BUSY				0x00000001
#define SD_CMD_DONE_MASK					0x0000000e
#define SD_CMD_DONE_CMD_DONE				0x00000002
#define SD_CMD_DONE_CRC_ERR			 		0x00000004
#define SD_CMD_DONE_TIMER_ERR				0x00000008
#define SD_DATA_TX_BUSY						0x00000010
#define SD_DATA_DONE_MASK					0x000007e0
#define SD_DATA_DONE_NORMAL					0x00000020
#define SD_DATA_DONE_CRC_ERR				0x00000040
#define SD_DATA_DONE_TIMEOUT				0x00000080
#define SD_DATA_DONE_BITS_ERR 				0x00000100
#define SD_DATA_DONE_FIFO_UNDER_ERR 		0x00000200
#define SD_DATA_DONE_FIFO_OVER_ERR 			0x00000400
#define SD_DATA_REQ							0x00000800
#define SD_CLR_STATUS						0x00000fff	// should be checked later !!!


/* HW_SD_CMD_CON  the value set command control register */
#define HW_SD_CMD_CON_START					(0x00000001)
#define HW_SD_CMD_CON_ENABLE				(0x00000100)
#define HW_SD_CMD_CON_HAVE_RES				(0x00010000)
#define HW_SD_CMD_CON_HAVE_LONG_RES			(0x00020000)

/* HW_SD_RSP_ARG1 */
#define SD_CARD_READY						0x80000000
#define SD_CARD_RCA							0xffff0000
#define SD_CARD_STATE						0x00001e00
#define SD_CARD_STATE_TRAN					0x00000800
#define SD_RDY4DATA							0x00000100
#define SD_RCV_ERROR						0xfff00000

#define SD_RD_1W							0x00000301
#define SD_RD_4W							0x00000b01
#define SD_WR_1W							0x00000101
#define SD_WR_4W							0x00000901


/* HW_SD_TIMEOUT */
#define SD_TIMEOUT_100ms					(gp_para_sd->sd_timeout)//0x04000000		// assume 25 mhz - 0x3d090
#define SD_TIMEOUT_10ms 					0x00004000		// assume 25 mhz - 0x3d090

/* HW_SD_BLOCK_CON */
#define SD_RST_VALID						0x00000000
#define SD_RST_INVALID						0x00000001

/* HW_SD_MASK */
#define SD_MASK_10_11_12					0x000003ff

/* HW_SD_SRAM_RDCLK_CON */
#define SD_CD_INVALID						0x00000000

/* HW_SD_CMD_ARG */
#define SD_CMDARG_ACMD41					0x00ff8000	// by kk
#define SD_CMDARG_4W						0x00000002
#define SD_CMDARG_1W						0x00000000
#define SD_CMDARG_CLRCD						0x00000000
#define SD_CMDARG_SETCD						0x00000001

/* SD card block size */
#define SD_BLOCK_SIZE						(gp_para_sd->sd_block_len)
#define SD_RCA_FOR_MMC						0x12340000

#define SD_CMD_TIME_OUT 					gp_para_sd->sd_cmd_timeout

#define SD_TYPE_SD							1
#define SD_TYPE_MMC							0

#define SD_FIFO_LEN							0x10

typedef enum _SD_CMD_ERR_E_
{
	RSP_SD_DATA_TIMEOUT,
	RSP_SD_DATA_ERR,
	RSP_SD_CMD_CRC_ERR,
	RSP_SD_CMD_TIMEOUT,
	RSP_SD_CMD_RSP_ERR,
	RSP_SD_PARA_INVALID
}SD_CMD_ERR_E;

typedef struct _SD_CONTROLLER_T_{
	union _SD_CONTROLLER_STATUS_U_{
		USTC_U32 v;
		struct _SD_CONTROLLER_STATUS_T_{
			unsigned cmd_busy:1;
			unsigned cmd_done:1;
			unsigned cmd_crc_err:1;
			unsigned cmd_timeout:1;
			unsigned data_tx_busy:1;
			unsigned data_tx_done:1;
			unsigned data_crc_err:1;
			unsigned data_timeout:1;
			unsigned wide_bus_start_bits_err:1;
			unsigned fifo_underflow:1;
			unsigned fifo_overflow:1;
			unsigned data_req:1;
			unsigned cmd_sent:1;
			unsigned card_insert:1;//interrupt
			unsigned card_remove:1;//interrupt
			unsigned card_exist:1;
		}bit_info;
	}status;
	union _SD_CONTROLLER_CMD_CFG_U_{
		USTC_U32 v;
		struct _SD_CONTROLLER_CMD_CFG_T_{
			unsigned start:1;
			unsigned reserved_1_7:7;
			unsigned tx_enable:1;
			unsigned pending:1;
			unsigned reserved_10_15:6;
			unsigned has_rsp:1;
			unsigned long_rsp:1;
			unsigned index:6;
		}bit_info;
	}cmd_cfg;
	USTC_U32	cmd_arg;
	USTC_U32	rsp_index;//bit[5:0]
	USTC_U32	rsp_arg[4];
	USTC_U32	timeout;
	union _SD_CONTROLLER_DATA_CFG_U_{
		USTC_U32 v;
		struct _SD_CONTROLLER_DATA_CFG_T_{
			unsigned tx_start:1;
			unsigned reserved_1_7:7;
			unsigned tx_enable:1;
			unsigned tx_direction:1;
			unsigned tx_mode:1;//0 block, 1 stream
			unsigned wide_bus:1;//0 for 1bit, 1 for 4bit
			unsigned reserved_12_15:4;
			unsigned blk_size:11;//in byte
		}bit_info;
	}data_cfg;
	union _SD_CONTROLLER_DATA_LEN_U_{
		USTC_U32 v;
		struct _SD_CONTROLLER_DATA_LEN_T_{
			unsigned tx_length:16;//transferred length
			unsigned remain_length:16;//need to be transferred
		}bit_info;
	}data_length;
	union _SD_CONTROLLER_MASK_U_{
		USTC_U32 v;
		struct _SD_CONTROLLER_MASK_T_{
			unsigned cmd_done:1;
			unsigned cmd_crc_err:1;
			unsigned cmd_timeout:1;
			unsigned data_tx_done:1;
			unsigned data_crc_err:1;
			unsigned data_timeout:1;
			unsigned wide_bus_start_bits_err:1;
			unsigned fifo_underflow:1;
			unsigned fifo_overflow:1;
			unsigned data_req:1;
			unsigned cmd_sent:1;
			unsigned card_insert:1;
			unsigned card_remove:1;
		}bit_info;
	}mask;
	union _SD_CONTROLLER_CLK_CFG_U_{
		USTC_U32 v;
		struct _SD_CONTROLLOER_CLK_CFG_T_{
			unsigned close_clk:1;
			unsigned void_fifo_err:1;
			unsigned reserved_2_7:6;
			unsigned clk_div_cnt:13;
		}bit_info;
	}clk_cfg;
	union _SD_CONTROLLER_POWER_CFG_U_{
		USTC_U32 v;
		struct _SD_CONTROLLER_POWER_CLK_T_{
			unsigned ctrl:2;
			unsigned volage:4;
			unsigned open_drain:1;
			unsigned rod_ctrl:1;
		}bit_info;
	}power_cfg;
	USTC_U32	soft_reset;//bit 0
	union _SD_CONTROLLER_IF_CFG_U_{
		USTC_U32 v;
		struct _SD_CONTROLLER_IF_CFG_T_{
			unsigned sd_data3_cfg:1;
			unsigned powerdown_ctrl:1;
			unsigned powerpull_ctrl:1;
			unsigned cd_enable:1;
			unsigned cd_hvalid:1;
			unsigned reserved_5_7:3;
			unsigned SDIF_OTIMING:1;
			unsigned SDIF_ITIMING:1;
		}bit_info;
	}SDIF_cfg;
	USTC_U32 debug1;
	union _SD_CONTROLLER_DEBUG2_U_{
		USTC_U32 v;
		struct _SD_CONTROLLER_DEBUG2_T_{
			unsigned host_word_count:14;
			unsigned reserved_14_16:2;
			unsigned valid_data_count:6;
		}bit_info;
	}debug2;
}SD_T;

//fs driver error code
enum
{
	FS_OP_OK,
	FS_OP_CARD_NEED_INIT,
	FS_CMD_ABORTED,
	FS_CMD_TIME_OUT,
	FS_DEV_CRC_ERR,
	FS_DEV_TIME_ERR,
	FS_DEV_ADDR_OUT_OF_RANGE,

	/* Data */
	FS_DATA_OK,
	FS_DATA_CRC_ERR,
	FS_DATA_TIMEOUT,
	FS_DATA_BITS_ERR,
	FS_DATA_FIFO_UNDER_ERR,
	FS_DATA_FIFO_OVER_ERR,

	/* the return value after init SD card  */
	FS_INIT_FAIL,

	/* the return value after write a block */
	FS_WRITE_BLOCK_FAIL,

	FS_ERASE_BLOCK_FAIL
};

typedef struct
{
	USTC_U16 c_size;			/*12bits */		
	USTC_U8 c_size_mult;   	 /*3bit */
	USTC_U8 read_block_len;    /* 4bits */
} CSD_T;

extern STATUS_T ustc_sdc_card_detect(void);
extern STATUS_T ustc_sdc_init(SD_PARA_T * p_para_sd);

extern STATUS_T ustc_sdc_read(unsigned long * p_buffer, unsigned long block_index, unsigned long num);
extern STATUS_T ustc_sdc_write(unsigned long * p_buffer, unsigned long block_index, unsigned long num);

#endif

